using System;
using System.ComponentModel;
using System.Linq.Expressions;
using System.Reflection;
using System.Waf.Applications;

public class BasicViewModel<TView> : ViewModel<TView> where TView : IView
{
	public BasicViewModel(TView view)
		: base(view)
	{
	}

	public BasicViewModel(TView view, bool isChild)
		: base(view, isChild)
	{
	}


	protected void RaisePropertyChanged<T>(Expression<Func<T>> propertyExpresssion)
	{
		string propertyName = ExtractPropertyName(propertyExpresssion);
		RaisePropertyChanged(propertyName);
	}

	private string ExtractPropertyName<T>(Expression<Func<T>> propertyExpression)
	{
		if (propertyExpression == null)
		{
			throw new ArgumentNullException("propertyExpression");
		}

		var memberExpression = propertyExpression.Body as MemberExpression;
		if (memberExpression == null)
		{
			throw new ArgumentException("The expression is not a member access expression.", "propertyExpression");
		}

		var property = memberExpression.Member as PropertyInfo;
		if (property == null)
		{
			throw new ArgumentException("The member access expression does not access a property.", "propertyExpression");
		}

		if (!property.DeclaringType.IsAssignableFrom(GetType()))
		{
			throw new ArgumentException("The referenced property belongs to a different type.", "propertyExpression");
		}

		MethodInfo getMethod = property.GetGetMethod(true);
		if (getMethod == null)
		{
			// this shouldn't happen - the expression would reject the property before reaching this far
			throw new ArgumentException("The referenced property does not have a get method.", "propertyExpression");
		}

		if (getMethod.IsStatic)
		{
			throw new ArgumentException("The referenced property is a static property.", "propertyExpression");
		}

		return memberExpression.Member.Name;
	}
}
